unit uUpdateApp;

interface

uses Forms, SysUtils, Oracle, Windows, gnugettext, dialogs, shellapi, strutils, synzip, uFrmLoading;

procedure CheckForApplicationUpdate(ApplicationName, APPUsername, APPPassword: string);
function FileLastModified(const Filename: string): TDateTime;
function GetDBFileBuildTime(ApplicationName: string): TDateTime;
procedure DownloadNewApplicationFilesFromDB(ApplicationName: string; BuildTimeInDB: TDateTime);
procedure RestartApplication(AApplicationName, APPUsername, APPPassword: string);
function GetExeParameterValue(AParameter: string): string;
procedure ExtractZipFile(AFileName: string; BuildTimeInDB: TDateTime);
procedure UpdateAPPVersionInDB(ApplicationName: string);
function CreateZipFile(ZipFile, ExeFile: string): boolean;
function GetFileVersion(const Filename: string; var Version: string): boolean;

implementation

uses umainutils;

function CreateZipFile(ZipFile, ExeFile: string): boolean;
begin
  result := True;
  with TZipWrite.Create(ZipFile) do
    try
      AddDeflated(ExeFile);
      assert(Count = 1);
      Free;
    except
      Free;
      result := false;
    end;
end;

function GetFileVersion(const Filename: string; var Version: string): boolean;
var
  VerBlk: VS_FIXEDFILEINFO;
  InfoSize, puLen: DWord;
  Pt, InfoPtr: Pointer;
begin
  Version := '';
  InfoSize := GetFileVersionInfoSize(PChar(Filename), puLen);
  FillChar(VerBlk, SizeOf(VS_FIXEDFILEINFO), 0);
  if InfoSize > 0 then
  begin
    GetMem(Pt, InfoSize);
    GetFileVersionInfo(PChar(Filename), 0, InfoSize, Pt);
    VerQueryValue(Pt, '\', InfoPtr, puLen);
    move(InfoPtr^, VerBlk, SizeOf(VS_FIXEDFILEINFO));
    Version := Format('%d.%d.%d.%d', [VerBlk.dwFileVersionMS shr 16, VerBlk.dwFileVersionMS and 65535, VerBlk.dwFileVersionLS shr 16, VerBlk.dwFileVersionLS and 65535]);
    FreeMem(Pt);
    result := True;
  end
  else
    result := false;
end;

procedure UpdateAPPVersionInDB(ApplicationName: string);
var
  ExeFile, ZipFile: string;
  ExeVersion, BuildDateSQL: string;
  AppBlob: TLobLocator;
  BuildDate: TDateTime;
begin
  ExeFile := ExtractFilePath(Application.ExeName) + ApplicationName;
  if FileExists(ExeFile) then
  begin
    ZipFile := ExtractFilePath(Application.ExeName) + MidStr(ApplicationName, 0, Length(ApplicationName) - 4) + 'Update.zip';
    if FileExists(ZipFile) then
      DeleteFile(PChar(ZipFile));
    if CreateZipFile(ZipFile, ExeFile) then
    begin
      if GetFileVersion(ExeFile, ExeVersion) then
      begin
        BuildDate := FileLastModified(ExeFile);
        try
          // create TblobLocator object
          AppBlob := TLobLocator.CreateTemporary(OraSessMainUtils, otBLOB, True);
          OraQueryMainUtils.SQL.Clear;
          OraQueryMainUtils.Variables.List.Clear;
          BuildDateSQL := FormatDateTime('dd.mm.yyyy hh:nn:ss', BuildDate);
          BuildDateSQL := 'to_date(''' + BuildDateSQL + ''', ''dd.mm.yyyy hh24:mi:ss'')';
          OraQueryMainUtils.SQL.Text := ('UPDATE APPLICATIONS SET BUILD_TIME=' + BuildDateSQL + ' , BIN=:APPLI WHERE APPLICATION_NAME=' + '''' + ApplicationName + '''');
          OraQueryMainUtils.DeclareVariable(':APPLI', otBLOB);
          OraQueryMainUtils.SetComplexVariable(':APPLI', AppBlob);
          AppBlob.LoadFromFile(ZipFile);
          OraQueryMainUtils.Execute;
          OraSessMainUtils.Commit;
          OraQueryMainUtils.Variables.List.Clear;
          OraQueryMainUtils.Close;
          DeleteFile(PChar(ZipFile));
        except
          ShowMessage(ApplicationName + _(' version update failed!'));
          AppBlob.Clear;
          AppBlob.Free;
          DeleteFile(PChar(ZipFile));
        end;
      end;
    end;
  end;
end;

function GetDBFileBuildTime(ApplicationName: string): TDateTime;
var
  TempCasinoSession: TOracleSession;
begin
  result := 0;
  try
    OraQueryMainUtils.Close;
    OraQueryMainUtils.SQL.Text := 'select build_time from applications where application_name=' + '''' + ApplicationName + '''';
    OraQueryMainUtils.Execute;
    result := OraQueryMainUtils.Field(0);
  except
    //
  end;
end;

function FileLastModified(const Filename: string): TDateTime;
var
  FileDateTime: TDateTime;
begin
  FileAge(Filename, FileDateTime);
  result := FileDateTime;
end;

procedure CheckForApplicationUpdate(ApplicationName, APPUsername, APPPassword: string);
var
  LocalFile, RenamedFile: WideString;
  LocalModifiedDateTime: TDateTime;
  BuildTimeInDB: TDateTime;
  FrmLoading: TFrmLoading;
begin
  LocalFile := Application.ExeName;
  LocalModifiedDateTime := FileLastModified(LocalFile);
  BuildTimeInDB := GetDBFileBuildTime(ApplicationName);
  if BuildTimeInDB - LocalModifiedDateTime > 0.0001 then
  begin
    if FrmLoading = nil then
      FrmLoading := TFrmLoading.Create(nil);
    FrmLoading.Label1.Caption := _('Updating Application...please wait');
    FrmLoading.Caption := FrmLoading.Label1.Caption;
    FrmLoading.Show;
    FrmLoading.ProgressBar1.Position := 30;
    FrmLoading.Repaint;
    RenamedFile := ChangeFileExt(LocalFile, '.BAK');
    try
      if FileExists(RenamedFile) then
      begin
        if not DeleteFile(PChar(RenamedFile)) then
        begin
          ShowMessage(_('Can not delete old application file') + ': ' + #13#10 + RenamedFile);
          ExitProcess(0);
        end;
        Application.ProcessMessages;
      end;
      if not RenameFile(LocalFile, RenamedFile) then
      begin
        ShowMessage(_('Can not rename current application file') + ': ' + #13#10 + LocalFile);
        ExitProcess(0);
      end;
      Application.ProcessMessages;
      FrmLoading.ProgressBar1.Position := 60;
      FrmLoading.Repaint;
      DownloadNewApplicationFilesFromDB(ApplicationName, BuildTimeInDB);
      FrmLoading.Close;
      FreeAndNil(FrmLoading);
      RestartApplication(LocalFile, APPUsername, APPPassword);
    except
      on E: Exception do
      begin
        DeleteFile(PChar(RenamedFile));
        RenamedFile := ChangeFileExt(LocalFile, '.EXE');
      end;
    end;
  end;
end;

procedure RestartApplication(AApplicationName, APPUsername, APPPassword: string);
var
  // EncodedPassword: string;
  Parameters: string;
  i: integer;
begin
  // EncodedPassword := uTools.EncodePWDEx(dmMain.SubjectPassword, SecurityString);
  ShellExecute(0, 'open', PChar(AApplicationName), PChar(APPUsername + ' ' + APPPassword + ' ' + 'LOGIN'), nil, SW_SHOWNORMAL);
  ExitProcess(0);
end;

function GetExeParameterValue(AParameter: string): string;
var
  Counter, SeparatorPosition: integer;
  ParamValue, ParamName: string;
begin
  result := '';
  Counter := 0;
  AParameter := AnsiUpperCase(AParameter);
  while Counter < ParamCount do
  begin
    ParamValue := ParamStr(Counter + 1);
    SeparatorPosition := Pos('=', ParamValue);
    if SeparatorPosition > 0 then
    begin
      ParamName := AnsiLeftStr(ParamValue, SeparatorPosition - 1);
      ParamName := AnsiUpperCase(ParamName);
      if AnsiSameStr(ParamName, AParameter) then
      begin
        Delete(ParamValue, 1, SeparatorPosition);
        result := AnsiUpperCase(ParamValue);
        Break;
      end;
    end;
    Counter := Counter + 1;
  end;
end;

procedure DownloadNewApplicationFilesFromDB(ApplicationName: string; BuildTimeInDB: TDateTime);
var
  orq_NewVersion: TOracleQuery;
  DownloadDir, NewFile: string;
  TempCasinoSession: TOracleSession;
  NewService: boolean;
begin
  NewService := false;
  DownloadDir := ExtractFileDir(Application.ExeName);
  NewFile := DownloadDir + '\LPMupdate.zip';
  if FileExists(NewFile) then
  begin
    if not DeleteFile(PChar(NewFile)) then
    begin
      ShowMessage(_('Can not delete old application files') + ': ' + #13#10 + NewFile);
      ExitProcess(0);
    end;
    Application.ProcessMessages;
  end;
  try
    OraQueryMainUtils.SQL.Clear;
    OraQueryMainUtils.SQL.Add('SELECT BIN FROM APPLICATIONS');
    OraQueryMainUtils.SQL.Add('WHERE APPLICATION_NAME=''' + ApplicationName + '''');
    OraQueryMainUtils.Execute;
    OraQueryMainUtils.LOBField(0).SaveToFile(NewFile);
    OraQueryMainUtils.Close;
  except
    on E: Exception do
    begin
      ShowMessage(_('Can not retrive new files from db!') + #13#10 + E.Message);
      ExitProcess(0);
    end;
  end;
  ExtractZipFile(NewFile, BuildTimeInDB);
end;

procedure ExtractZipFile(AFileName: string; BuildTimeInDB: TDateTime);
var
  myZip: TZipRead;
  i: integer;
  DirectoryName, Filename: string;
begin
  myZip := TZipRead.Create(AFileName);
  DirectoryName := ExtractFileDir(Application.ExeName);
  for i := 0 to myZip.Count - 1 do
  begin
    Filename := String(TZipEntry(myZip.Entry[i]).Name);
    if myZip.UnZip(i, DirectoryName) then
    begin
      // Now change the last modified date
      FileSetDate(DirectoryName + '\' + Filename, DateTimeToFileDate(BuildTimeInDB));
    end
    else
    begin
      ShowMessage(_('Error extracting data!'));
      ExitProcess(0);
    end;
  end;
  myZip.Free;
  DeleteFile(PChar(AFileName));
end;

end.
